<template>
	<div class="app-container">
		<doc-alert
			title="WebSocket 实时通信"
			url="https://doc.iocoder.cn/websocket/"
		/>

		<el-form label-width="120px">
			<el-row
				type="flex"
				:gutter="0"
			>
				<el-col :sm="12">
					<el-form-item
						label="WebSocket地址"
						size="small"
					>
						<el-input
							v-model="url"
							type="text"
						/>
					</el-form-item>
				</el-col>
				<el-col :offset="1">
					<el-form-item
						label=""
						label-width="0px"
						size="small"
					>
						<el-button
							@click="connect"
							type="primary"
							:disabled="ws && ws.readyState === 1"
						>
							{{ ws && ws.readyState === 1 ? '已连接' : '连接' }}
						</el-button>
						<el-button
							@click="exit"
							type="danger"
							>断开</el-button
						>
					</el-form-item>
				</el-col>
			</el-row>
			<el-form-item
				label="发给谁"
				size="small"
			>
				<el-select
					v-model="sendUserId"
					placeholder="请选择"
				>
					<el-option
						label="所有人"
						:value="null"
					/>
					<el-option
						v-for="item in userList"
						:key="item.id"
						:label="item.nickname"
						:value="item.id"
					>
					</el-option>
				</el-select>
			</el-form-item>
			<el-form-item
				label="发送内容"
				size="small"
			>
				<el-input
					type="textarea"
					v-model="sendText"
					:rows="5"
				/>
			</el-form-item>
			<el-form-item
				label=""
				size="small"
			>
				<el-button
					type="success"
					@click="send"
					>发送消息</el-button
				>
			</el-form-item>
			<el-form-item
				label="接收内容"
				size="small"
			>
				<el-input
					type="textarea"
					v-model="content"
					:rows="12"
					disabled
				/>
			</el-form-item>
			<el-form-item
				label=""
				size="small"
			>
				<el-button
					type="info"
					@click="content = ''"
					>清空消息</el-button
				>
			</el-form-item>
		</el-form>
	</div>
</template>

<script>
import { getNowDateTime } from '@/utils/ruoyi';
import { getAccessToken } from '@/utils/auth';
import { listSimpleUsers } from '@/api/system/user';

export default {
	data() {
		return {
			url: '',
			sendText: '',
			content: '',
			ws: null,
			userList: [], // 用户列表
			sendUserId: null, // 发给谁，默认所有人
		};
	},
	created() {
		const wsUrl =
			`${window.location.protocol}//${window.location.host}/api` +
			'/infra/ws' +
			'?token=' +
			getAccessToken();
		this.url = wsUrl.replace('http', 'ws');
		// 获取用户精简信息列表
		listSimpleUsers().then(res => {
			this.userList = res.data;
		});
	},
	methods: {
		/** 发起连接 */
		connect() {
			if ((!'WebSocket') in window) {
				this.$modal.msgError('您的浏览器不支持WebSocket');
				return;
			}
			// 建立连接
			this.ws = new WebSocket(this.url);
			// 监听 open 事件
			this.ws.onopen = event => {
				this.content = this.content + '\n**********************连接开始**********************\n';
			};
			// 监听 message 事件
			this.ws.onmessage = event => {
				try {
					const data = event.data;
					// 1. 收到心跳
					if (data === 'pong') {
						return;
					}
					// 2.1 解析 type 消息类型
					const jsonMessage = JSON.parse(data);
					const type = jsonMessage.type;
					const content = JSON.parse(jsonMessage.content);
					if (!type) {
						this.$modal.msgError('未知的消息类型：' + data);
						return;
					}
					// 2.2 消息类型：demo-message-receive
					if (type === 'demo-message-receive') {
						const single = content.single;
						this.content =
							this.content +
							'接收时间：' +
							getNowDateTime() +
							'\n' +
							`【${single ? '单发' : '群发'}】用户编号(${content.fromUserId})：${content.text}` +
							'\n';
						return;
					}
					// 2.3 消息类型：notice-push
					if (type === 'notice-push') {
						this.content =
							this.content +
							'接收时间：' +
							getNowDateTime() +
							'\n' +
							`【系统通知】：${content.title}` +
							'\n';
						return;
					}
					this.$modal.msgError('未处理消息：' + data);
				} catch (error) {
					this.$modal.msgError('处理消息发生异常：' + event.data);
					console.error(error);
				}
			};
			// 监听 close 事件
			this.ws.onclose = event => {
				this.content = this.content + '**********************连接关闭**********************\n';
			};
			// 监听 error 事件
			this.ws.error = event => {
				this.content = this.content + '**********************连接异常**********************\n';
			};
		},
		/** 关闭连接 */
		exit() {
			if (this.ws) {
				this.ws.close();
				this.ws = null;
			}
		},
		/** 发送消息 */
		send() {
			if (!this.ws || this.ws.readyState !== 1) {
				this.$modal.msgError('未连接到服务器');
				return;
			}
			if (!this.sendText) {
				this.$modal.msgError('请输入发送内容');
				return;
			}

			// 1.1 先 JSON 化 message 消息内容
			const messageContent = JSON.stringify({
				text: this.sendText,
				toUserId: this.sendUserId,
			});
			// 1.2 再 JSON 化整个消息
			const jsonMessage = JSON.stringify({
				type: 'demo-message-send',
				content: messageContent,
			});
			// 2. 最后发送消息
			this.ws.send(jsonMessage);
			this.sendText = '';
		},
	},
};
</script>
